
--------------------------------------------------------------------------
-- 运营活动 抽奖模块
--#author:zhaoyongbo
--time:2021-09-07
--
--------------------------------------------------------------------------

-- 文件
local gg         = require("modules.business_welfare.welfare_gg")
local config     = require("modules.business_welfare.welfare_lua_config")
local uu         = require("modules.commhm.utils")
local ns_account = require("modules.business_welfare.welfare_bridge")
local log        = require("modules.commhm.log")
local code_conf  = require("modules.business_welfare.welfare_code")
local g_enum     = require("modules.business_welfare.welfare_enum")
local business_welfare_common = require("modules.business_welfare.welfare_common")
local op_log     = require("modules.business_welfare.welfare_op_log")
local utils      = require("modules.business_common.business_utils")
local account    = require("modules.business_common.business_account")


-- 变量 开头定义优先级 系统库 > ngx > 自定义
local pairs      = pairs
local math       = math
local random = gg.random
local table_insert = table.insert
local ngx = ngx

local error_code = code_conf.error_code


local FOO = {
    _VERSION = '0.12.1',
}


FOO.MAX_GET_GIFT_LIME = 100  --从池中捞取的最大次数限制


FOO.get_xls_cfg = function(gift_id)
    local cfg = config.get_cfg('welfare_gift')
    return cfg and cfg.xls[gift_id]
end


--! @ 读配置， 通过物品id得到礼包id
FOO.get_id_cfg = function(item_id)
    local cfg = config.get_cfg('welfare_gift')
    return cfg and cfg.itemid2giftid[item_id]
end


--! @ 读带有类型的物品
FOO.get_type_item_cfg = function(item_id)
    local cfg = config.get_type_item()
    return cfg and cfg[item_id]
end


--! @ 获取物品类型
local get_type = function(id)
    local cfg = FOO.get_type_item_cfg(id)
    return cfg and cfg.ShowType, cfg and cfg.ShowId
end


FOO.get_mall_cfg = function(id)
    local cfg = config.get_cfg('welfare_gift_mall')
    return cfg and cfg[id]
end

FOO.get_mount_mall_cfg = function(id)
    local cfg = config.get_cfg('welfare_mount_mall')
    return cfg and cfg[id]
end


--! @ TODO test
FOO.test = function()
    local gift_id = tonumber(ngx.ctx.m_params.gift_id) or 1001
    local times = tonumber(ngx.ctx.m_params.times) or 1

    -- 2 获取玩家数据
    local userdata = gg.get_ssdb_cache_info(gg.KEYS.WELFARE_GIFT)
    if not userdata then
        return error_code.ERROR_NO_DATA
    end

    local ret, items = FOO.get_gift(userdata, gift_id, times)

    gg.set_ssdb_cache_info(gg.KEYS.WELFARE_GIFT, userdata)
    log.loggerdebug("礼包配置： %%", config.cfg["welfare_gift"].xls[gift_id])

    return ret, {items=items}
end


FOO.PRICE_TYPE = {
    [1] = g_enum.item_id.minibi,  --迷你币
    [2] = g_enum.item_id.minidou, --迷你豆
    [3] = g_enum.item_id.mount_lotterites, --坐骑抽奖
    [4] = g_enum.item_id.dream_lottery, --便宜扭蛋券
    [5] = g_enum.item_id.star_lottery,  --贵扭蛋券
}


----------------------------------------------------------------
--  对客户端提供的接口
----------------------------------------------------------------
FOO.welfare_gift_get_info = function()
    -- 1 获取玩家数据 只读
    local userdata = gg.get_ssdb_cache_info(gg.KEYS.WELFARE_GIFT, 1) or {}
    FOO.buy_flush_limit(userdata)
    local lucky_values = userdata.lucky_value or {}
    local limit_buy = userdata.limit_buy or {}

    return error_code.COMMON_SUCCESS, {lucky_values=lucky_values, limit_buy=limit_buy}
end


--! @ 礼包购买
FOO.welfare_gift_buy_gift = function()
    local buy_id = tonumber(ngx.ctx.m_params.buy_id) or 0
    local buy_times = tonumber(ngx.ctx.m_params.buy_times) or 0

    --配置检查
    local cfg = FOO.get_mall_cfg(buy_id)
    if not cfg then
        return error_code.ERROR_CONFIG
    end

    --检查时间
    local now = uu.now()
    if now < cfg.online or now > cfg.offline then
        return error_code.ERROR_LIMIT_TIME
    end

    -- 2 获取玩家数据
    local userdata = gg.get_ssdb_cache_info(gg.KEYS.WELFARE_GIFT)
    if not userdata then
        return error_code.ERROR_NO_DATA
    end

    -- 检查限购次数
    if not FOO.buy_limit_check(cfg, userdata, buy_id, buy_times) then
        return error_code.ERROR_LIMIT_TIMES
    end

    --赠送次数
    local give_times = 0
    if cfg.moreadd and cfg.moreadd > 0 then
        give_times = math.floor(buy_times/cfg.moreadd) --每10个送1个
    end

    local cost_id = FOO.PRICE_TYPE[cfg.pricetype]
    local ret, items = FOO.use_item_get_gift(userdata, cfg.giftid, cost_id, cfg.price, buy_times, 'welfare_gift_buy', give_times, buy_id)
    if ret ~= error_code.COMMON_SUCCESS then
        return ret
    end

    --记录购买次数
    FOO.buy_times_recording(cfg, userdata, buy_id, buy_times)

    gg.set_ssdb_cache_info(gg.KEYS.WELFARE_GIFT, userdata)

    return ret, items
end


--! @ 使用物品开启礼包
FOO.welfare_gift_use_item = function()
    local item_id = tonumber(ngx.ctx.m_params.item_id) or 0
    local times = tonumber(ngx.ctx.m_params.times) or 0

    local gift_id = FOO.get_id_cfg(item_id)
    if not gift_id then
        return error_code.ERROR_CONFIG
    end

    -- 2 获取玩家数据
    local userdata = gg.get_ssdb_cache_info(gg.KEYS.WELFARE_GIFT)
    if not userdata then
        return error_code.ERROR_NO_DATA
    end
    local ret, items = FOO.use_item_get_gift(userdata, gift_id, item_id, 1, times, 'welfare_gift_use_item', 0, 0)
    if ret ~= error_code.COMMON_SUCCESS then
        return ret
    end
    gg.set_ssdb_cache_info(gg.KEYS.WELFARE_GIFT, userdata)
    return ret, items
end


--! @ 礼包购买
FOO.welfare_gift_buy_mount = function()
    local buy_id = tonumber(ngx.ctx.m_params.buy_id) or 0
    local buy_times = tonumber(ngx.ctx.m_params.buy_times) or 0

    --配置检查
    local cfg = FOO.get_mount_mall_cfg(buy_id)
    if not cfg then
        return error_code.ERROR_CONFIG
    end

    --检查时间
    local now = uu.now()
    if now < cfg.online or now > cfg.offline then
        return error_code.ERROR_LIMIT_TIME
    end

    -- 2 获取玩家数据
    local userdata = gg.get_ssdb_cache_info(gg.KEYS.WELFARE_GIFT)
    if not userdata then
        return error_code.ERROR_NO_DATA
    end


    local cost_id = FOO.PRICE_TYPE[cfg.pricetype]
    local ret, items = FOO.use_item_get_gift(userdata, cfg.giftid, cost_id, cfg.price, buy_times, 'welfare_mount_gift', 0, buy_id)
    if ret ~= error_code.COMMON_SUCCESS then
        log.day_list("welfare_add_item", ngx.ctx.m_params.uin, uu.to_str(items), uu.now(), uu.to_str(ret))
        return ret
    end


    gg.set_ssdb_cache_info(gg.KEYS.WELFARE_GIFT, userdata)

    return ret, items
end


--! @ 使用物品开启礼包 gift_id:礼包id  item_id:物品id item_num:开启一个礼包消耗的物品数量 times:次数
FOO.use_item_get_gift = function(userdata, gift_id, item_id, item_num, times, action, give_times, buy_id)
    --检查参数
    if times < 1 or times > FOO.MAX_GET_GIFT_LIME then  --单次购买次数限制在 1-20
        return error_code.ERROR_PARAM
    end

    local orderid = string.format("gift_%s_%s_%s",ngx.ctx.m_params.uin, uu.now(), random(1,99999))
    local loginfo = {action=action, gift_id=gift_id, id=item_id, num=item_num, give_times=give_times, times=times, buy_id=buy_id, orderid=orderid, list={}}

    give_times = give_times or 0 -- 赠送次数
    local ret, drop_items, lucky_value, detail_items = FOO.get_gift(userdata, gift_id, times, give_times, loginfo)
    if ret ~= error_code.COMMON_SUCCESS then
        log.loggerdebug("welfare gift drops err uin:%% gift_id:%%, times：%%", ngx.ctx.m_params.uin, gift_id, times)
        return ret
    end

    --扣除消耗物品
    local ret = ns_account.private_account.item_remove(item_id, item_num*times, action)
    if not ret then
        log.loggerdebug("welfare gift del monkey item error, ret = %%", ret)
        return error_code.ERROR_DEL_ITEM
    end

    local items = {}
    for _, v in pairs(detail_items or {}) do
        for id, num in pairs(v) do
            items[#items+1] = {id=id, num=num}
        end
    end

    local ret = ns_account.private_account.items_add(items, action)
	if not ret then
        log.day_list("welfare_add_item", action, ngx.ctx.m_params.uin, uu.to_str(drop_items), uu.now(), uu.to_str(ret))
		return error_code.ERROR_ADD_ITEM
	end

    local detail_items_list = {
        welfare_mount_gift = true,
    }

    if detail_items_list[action]  then
        drop_items = detail_items
    end
    FOO.write_op_log(loginfo)
    return error_code.COMMON_SUCCESS, {items=drop_items, lucky_value=lucky_value, gift_id=gift_id}
end


-----------------------------------------------------------------
--  礼包抽奖逻辑实现
-----------------------------------------------------------------

--! @ 礼包抽奖
    --[[
        传入一个礼包id
        返回：抽奖的物品列表
        返回格式： {
            { id = 10000, num = 1},
            { id = 10001, num = 1},
        }
    ]]
FOO.get_gift = function(userdata, gift_id, times, give_times, loginfo)
    times = times or 1
    give_times = give_times or 0

    -- 1 检查配置
    local cfg = FOO.get_xls_cfg(gift_id)
    if not cfg or not cfg.check_item_type then
        return error_code.ERROR_CONFIG
    end

    -- 3 幸运值和抽奖次数
    userdata.lucky_value = userdata.lucky_value or {}
    userdata.times = userdata.times or {}
    userdata.lucky_value[gift_id] = userdata.lucky_value[gift_id] or cfg.luckylimit[1]
    userdata.times[gift_id] = userdata.times[gift_id] or 0

    -- 3 账号服的物品数据
    local ret, bag_items = FOO.query_user_bag(cfg.check_item_type)
    if ret ~= error_code.COMMON_SUCCESS then
        return ret
    end
    log.loggerdebug("已拥有的物品列表: %%", bag_items)

    -- 4 整理礼包的数据
    local drop_items = {}
    local detail_items = {}
    local is_give = false
    for i = 1, times + give_times do
        if i > times then
            is_give = true
        end
        userdata.times[gift_id] = userdata.times[gift_id] + 1 --记录玩家总抽奖次数
        local ret_items = FOO.do_get_gift(cfg, userdata, gift_id, bag_items, userdata.times[gift_id], loginfo, is_give)
        for id, num in pairs(ret_items) do
            drop_items[id] = (drop_items[id] or 0) + num
        end
        table.insert(detail_items, ret_items)
    end

    local ret_items = {}
    for id, num in pairs(drop_items) do
        table.insert(ret_items, {id=id, num=num})
    end

    return  error_code.COMMON_SUCCESS, ret_items, userdata.lucky_value[gift_id], detail_items
end


FOO.do_get_gift = function(cfg, data, gift_id, bag_items, times, loginfo, is_give)
    -- 日志打点用
    local logs = {
        lucky_value = data.lucky_value[gift_id],
        must = { items = {}, rate_list = {}},
        lucky = { items = {}, rate_list = {}},
        random = {items = {}, rate_list = {}},
        bag_items = bag_items,
        is_give = is_give,
        times = times,
    }

    -- 检查幸运值
    local is_lucky = FOO.check_lucky_value(cfg, data, gift_id)
    if is_lucky then    --幸运值满了后幸运值重置
        data.lucky_value[gift_id] = cfg.luckylimit[1] --幸运值下限
    else
        data.lucky_value[gift_id] = data.lucky_value[gift_id] + FOO.get_lucky_value(cfg)
    end

    logs.new_lucky_value = data.lucky_value[gift_id] --最新幸运值
    local drop_items,  _items = {}, {}

    -- 必得物品
    _items = FOO.get_must_items(cfg, logs)
    FOO.combine_items(drop_items, _items)

    --幸运物品
    if is_lucky then
        _items = FOO.get_lucky_items(cfg, bag_items, logs)
        FOO.combine_items(drop_items, _items)
    else
        --随机物品
        _items = FOO.get_random_items(cfg, bag_items, logs)
        FOO.combine_items(drop_items, _items)
    end

    FOO.write_log(logs, times)
    if loginfo then --埋点日志
        logs.drop_items = drop_items
        table_insert(loginfo.list, logs)
    end

    return drop_items
end


--! @ 获得幸运值数量
FOO.get_lucky_value = function(cfg)
    return random(cfg.luckyvalue[1], cfg.luckyvalue[2])
end


--! @ 必得物品池捞取
FOO.get_must_items = function(cfg, logs)
    local must_item_pool = cfg.must_item
    local items = {}

    for k, pool in pairs(must_item_pool) do
        local pool_rate = math.floor(pool.pool_rate * 1000)  --抽奖池权重
        local random_rate = random(1, 1000)                  --抽奖随机
        local num = 0                                        --抽到的物品数量

        if random_rate <= pool_rate then
            num = random(pool.min, pool.max)
            items[pool.id] = (items[pool.id] or 0) + num
        end
        -- 记录日志
        table.insert(logs.must.rate_list, {k=k, all_rate=1000, pool_rate=pool_rate, random_rate=random_rate, itemid=pool.id, itemnum=num})
    end
    logs.must.items = items

    return items
end


--! @ 幸运物品池捞取
FOO.get_lucky_items = function(cfg, bag_items, logs)
    local lucky_pool = cfg.lucky1 or {}
    if not next(lucky_pool) then
        return {}
    end

    -- 1 计算总权重
    local all_rate = 0
    local rate_list = {}
    for _, item in ipairs(lucky_pool or {}) do
        local item_type, show_id = get_type(item.id)
        local is_own =  FOO.query_is_own_item(item_type, bag_items, item.id, show_id)
        local is_own_rate = FOO.item_is_own_rate(is_own, cfg.luckyeffect1[2], cfg.luckyeffect1[1])
        all_rate = all_rate + FOO.get_item_rate(item.rate, is_own_rate, item.rate_up, item.open, item.close)
        table.insert(rate_list, all_rate*100000)
    end

    if all_rate == 0 then   --概率为零
        return {}
    end

    -- 2 得到随机物品
    local random_rate = random(1, all_rate*100000)
    local item_key
    for k, rate in ipairs(rate_list) do
        if random_rate <= rate then
            item_key = k
            break
        end
    end

    local id = lucky_pool[item_key].id
    local item_cfg = FOO.get_type_item_cfg(id) or {}
    local item_type = item_cfg.ShowType
    local drop_items = { [id] = lucky_pool[item_key].num }

    -- 将抽出的物品加入已拥有列表 ShowQuality= 4 为永久
    if item_cfg and item_cfg.ShowId and FOO.EXCHANGE_ITEM_TYPE[item_type] == item_type and item_cfg.ShowQuality == 4 then
        bag_items[item_type] = bag_items[item_type] or {}
        bag_items[item_type][item_cfg.ShowId] = true
    end

    --记录日志
    table.insert(logs.lucky.rate_list, {all_rate=all_rate, rate_list=rate_list, random_rate=random_rate})
    logs.lucky.items = drop_items

    return drop_items
end


--! @ 随机物品池捞取
FOO.get_random_items = function(cfg, bag_items, logs)
    local random_pool = cfg.random_item or {}
    if not next(random_pool) then
        return {}
    end

    local items = {}
    for _, info in ipairs(random_pool) do
        local pool_rate = math.floor(info.randomrate * 1000)
        local random_rate = random(1, 1000)
        local _log = {all_rate=1000, pool_rate=pool_rate,random_rate=random_rate}

        if random_rate <= pool_rate then
            local id, num = FOO.do_get_random_item(info, bag_items, _log)
            if id and num then
                items[id] = (items[id] or 0) + num
            end
        end

        --记录日志
        table.insert(logs.random.rate_list, _log)
    end
    logs.random.items = items

    return items
end


FOO.do_get_random_item = function(info, bag_items, _log)
    -- 1 计算总权重
    local all_rate = 0
    local rate_list = {}
    for _, item in ipairs(info.pool or {}) do
        local item_type, show_id = get_type(item.id)
        local is_own =  FOO.query_is_own_item(item_type, bag_items, item.id, show_id)
        local is_own_rate = FOO.item_is_own_rate(is_own, 0, 1)
        all_rate = all_rate + FOO.get_item_rate(item.rate, is_own_rate, item.rate_up, item.open, item.close)
        table.insert(rate_list, all_rate*100000)
    end

    if all_rate == 0 then
        return
    end

    -- 2 得到随机物品
    local random_rate = random(1, all_rate*100000)
    local item_key
    for k, rate in ipairs(rate_list) do
        if random_rate <= rate then
            item_key = k
            break
        end
    end

    local id = info.pool[item_key].id
    local item_cfg = FOO.get_type_item_cfg(id) or {}
    local item_type = item_cfg.ShowType
    local num = info.pool[item_key].num

    -- 3 记录日志
    _log.list = {all_rate=all_rate, rate_list=rate_list, random_rate=random_rate, itemid=id, itemnum=num}

    -- 将抽出的物品加入已拥有列表 ShowQuality= 4 为永久， 这里
    if item_cfg and item_cfg.ShowId and FOO.EXCHANGE_ITEM_TYPE[item_type] == item_type and item_cfg.ShowQuality == 4 then
        bag_items[item_type] = bag_items[item_type] or {}
        bag_items[item_type][item_cfg.ShowId] = true
    end

    return id, num
end


--! @ 检查幸运值有没有满
FOO.check_lucky_value = function(cfg, data, gift_id)
    if data.lucky_value[gift_id] >= cfg.luckylimit[2] and cfg.luckylimit[2] ~= 0 then
        return true
    end
    return false
end


--! @ 是否已拥有的概率
FOO.item_is_own_rate = function(is_own, is_own_rate, not_own_rate)
    if is_own then
        return is_own_rate
    end
    return not_own_rate
end


--! @ 概率上升倍数
FOO.item_rate_up = function(rate_up)
    if not rate_up then
        return 1
    end
    local now = uu.now()
    if now >= rate_up.starttime and now <= rate_up.endtime then
        return rate_up.up_mul
    end
    return 1
end


--! @ 物品 open 上架检查
FOO.item_open = function(open)
    if not open then
        return 1
    end
    local now = uu.now()
    if now < open.time then
        return open.up_mul
    end
    return 1
end


--! @ 物品 close 检查
FOO.item_close = function(close)
    if not close then
        return 1
    end
    local now = uu.now()
    if now >= close.time then
        return close.up_mul
    end
    return 1
end


--! @ 单个物品的概率整合
FOO.get_item_rate = function(src_rate, is_own_tate, rate_up, open, close)
    src_rate = src_rate * is_own_tate
    src_rate = src_rate * FOO.item_rate_up(rate_up)
    src_rate = src_rate * FOO.item_open(open)
    src_rate = src_rate * FOO.item_close(close)
    return src_rate
end


--! @ 物品合并
FOO.combine_items = function(drop_items, items)
    for id, num in pairs(items) do
        drop_items[id] = (drop_items[id] or 0) + num
    end
    return drop_items
end


-----------------------------------------------
-----  查询是否已拥有相关接口
-----------------------------------------------
FOO.EXCHANGE_ITEM_TYPE = {
    [g_enum.bag.item_type.avatar] =  g_enum.bag.item_type.avatar,
    [g_enum.bag.item_type.avatar_box] = g_enum.bag.item_type.avatar_box,
    [g_enum.bag.item_type.avatar_splinter] = g_enum.bag.item_type.skin,
    [g_enum.bag.item_type.skin] = g_enum.bag.item_type.skin,
    [g_enum.bag.item_type.mount] = g_enum.bag.item_type.mount,
    [g_enum.bag.item_type.weponskin] = g_enum.bag.item_type.weponskin,
    [g_enum.bag.item_type.painting] = g_enum.bag.item_type.painting,
}


--! @查询是否拥有物品
FOO.query_is_own_item = function(item_type, bag_items, item_id, show_id)
    item_type = FOO.EXCHANGE_ITEM_TYPE[item_type]
    if not item_type or not bag_items[item_type] then
        return false
    end
    local id = show_id or item_id  --有资源id则映射资源id
    return bag_items[item_type][id]
end


--! @ 查询已拥有的永久皮肤
FOO.owned_skin_list = function()
    local ret = {}
    local rst, list = account.query_owned_skin_account()
    if not rst then
        log.error('gift query skin error')
        return error_code.ERROR_REQ_TIMEOUT
    end
    for _, v in ipairs(list or {}) do
        ret[v] = true  -- skinid = true
    end
    return error_code.COMMON_SUCCESS, ret
end


--! @ 查询已拥有的永久avatar
FOO.owned_avatar_list = function()
    local ret = {}
    local rst, list = account.query_owned_avatar_account()
    if not rst then
        log.error('gift query avatar error')
        return error_code.ERROR_REQ_TIMEOUT
    end
    for _, v in ipairs(list or {}) do
        ret[v] = true -- avatar_id = true
    end
    return error_code.COMMON_SUCCESS, ret
end


--! @ 查询已拥有的永久头像框
FOO.owned_avatar_box_list = function()
    local ret = {}
    local rst, list = account.query_owned_box_account()
    if not rst then
        log.error('gift query box error')
        return error_code.ERROR_REQ_TIMEOUT
    end
    for _, v in ipairs(list or {}) do
        ret[v] = true -- avatar_id = true
    end
    return error_code.COMMON_SUCCESS, ret
end


--! @ 查询已拥有的坐骑列表
FOO.owned_mount_list = function()
    local ret = {}
    local rst, list = account.query_owned_mount_account()
    if not rst then
        log.error('gift query mount error')
        return error_code.ERROR_REQ_TIMEOUT
    end
    for _, v in ipairs(list or {}) do
        ret[v] = true -- avatar_id = true
    end
    return error_code.COMMON_SUCCESS, ret
end


--! @ 查询已拥有的武器装扮列表
FOO.owned_weponskin_list = function ()
    local ret = {}
    local succ, list = account.query_owned_weponskin()
    if not succ then
        log.error('gift query weponskin error')
        return error_code.ERROR_REQ_TIMEOUT
    end
    for _, v in ipairs(list or {}) do
        ret[v] = true -- avatar_id = true
    end
    
    return error_code.COMMON_SUCCESS, ret
end


--! @ 查询已拥有的喷漆图案列表
FOO.owned_painting_list = function ()
    local ret = {}
    local succ, list = account.query_owned_spraypaints()
    if not succ then
        log.error('gift query painting error')
        return error_code.ERROR_REQ_TIMEOUT
    end
    for _, v in ipairs(list or {}) do
        ret[v] = true -- avatar_id = true
    end

    return error_code.COMMON_SUCCESS, ret
end

--! @ 从账号服拉去数据的函数列表
FOO.QURE_LIST = {
    [g_enum.bag.item_type.skin] = FOO.owned_skin_list,                  --皮肤列表
    [g_enum.bag.item_type.avatar] = FOO.owned_avatar_list,              --avatar列表
    [g_enum.bag.item_type.avatar_box] = FOO.owned_avatar_box_list,      --头像框列表
    [g_enum.bag.item_type.mount] = FOO.owned_mount_list,                --坐骑列表
    [g_enum.bag.item_type.weponskin] = FOO.owned_weponskin_list,        --武器装扮
    [g_enum.bag.item_type.painting] = FOO.owned_painting_list,          --喷漆图案
}


--! @ 从帐号服拉去背包数据 用于查询玩家是否已拥有
FOO.query_user_bag = function(gift_item)
    -- 1. 统计类型
    local type_list = {}
    for id, _ in pairs(gift_item or {}) do
        local type_item = FOO.get_type_item_cfg(id)
        log.loggerdebug("type item id: %%, %%", id, type_item)
        if type_item and type_item.ShowType then
            type_list[type_item.ShowType] = true
        end
    end
    log.loggerdebug("type list: %%, %%", type_list, gift_item)
    -- 2.优化，只查询该礼包包含的物品类型的类型列表
    local items = {}
    for type, func in pairs(FOO.QURE_LIST) do
        if type_list[type] then
            local ret, list = func()
            if ret == error_code.COMMON_SUCCESS then
                items[type] = list
            else
                return ret
            end
        end
    end
    return error_code.COMMON_SUCCESS, items
end


-----------------------------------------------------------------------
-- 购买限购相关
-----------------------------------------------------------------------
FOO.buy_flush_limit_by_type = function(data, type, func)
    data.limit_buy = data.limit_buy or {}
    data.limit_buy[type] = data.limit_buy[type] or {}
    local flush_time = data.limit_buy[type].flush_time

    -- 刷新时间是同一时间段则返回
    local now = uu.now()
    if flush_time and func(now, flush_time) then
        return
    end

    data.limit_buy[type].flush_time = now

    for _, info in pairs(data.limit_buy[type].buy_list or {}) do
        info.times = 0   --购买次数清零
    end
end


--每日刷新
FOO.buy_flush_by_day = function(data)
    local func = business_welfare_common.is_same_day
    FOO.buy_flush_limit_by_type(data, g_enum.gift.limit_buy_type.day, func)
end


--每周刷新
FOO.buy_flush_by_weekly = function(data)
    local func = business_welfare_common.is_same_week
    FOO.buy_flush_limit_by_type(data, g_enum.gift.limit_buy_type.weekly, func)
end


--每月刷新
FOO.buy_flush_by_month = function(data)
    local func = business_welfare_common.is_same_month
    FOO.buy_flush_limit_by_type(data, g_enum.gift.limit_buy_type.month, func)
end


FOO.FLUSH_BUY_LIMIT = {
    [g_enum.gift.limit_buy_type.day] = FOO.buy_flush_by_day,
    [g_enum.gift.limit_buy_type.weekly] = FOO.buy_flush_by_weekly,
    [g_enum.gift.limit_buy_type.month] = FOO.buy_flush_by_month,
}


--购买刷新限制
FOO.buy_flush_limit = function(userdata)
    for _, func in pairs(FOO.FLUSH_BUY_LIMIT) do
        func(userdata)
    end
end


--购买限购检查
FOO.buy_limit_check_by_type = function(cfg, data, buy_id, type, buy_times)
    data.limit_buy = data.limit_buy or {}
    data.limit_buy[type] = data.limit_buy[type] or {}
    data.limit_buy[type].buy_list = data.limit_buy[type].buy_list or {}
    data.limit_buy[type].buy_list[buy_id] = data.limit_buy[type].buy_list[buy_id] or {}
    local times = data.limit_buy[type].buy_list[buy_id].times or 0

    return (times + buy_times) <= (cfg.limit or 0) --购买次数小于限购次数
end


FOO.BUY_LIMIT_CHECK = {
    [g_enum.gift.limit_buy_type.no_limit] = function(cfg, data, buy_id, buy_times)
        return true
    end,
    [g_enum.gift.limit_buy_type.day] = function (cfg, data, buy_id, buy_times)
        return FOO.buy_limit_check_by_type(cfg, data, buy_id, g_enum.gift.limit_buy_type.day, buy_times)
    end,
    [g_enum.gift.limit_buy_type.weekly] = function (cfg, data, buy_id, buy_times)
        return FOO.buy_limit_check_by_type(cfg, data, buy_id, g_enum.gift.limit_buy_type.weekly, buy_times)
    end,
    [g_enum.gift.limit_buy_type.month] = function (cfg, data, buy_id, buy_times)
        return FOO.buy_limit_check_by_type(cfg, data, buy_id, g_enum.gift.limit_buy_type.month, buy_times)
    end,
    [g_enum.gift.limit_buy_type.forever] = function(cfg, data, buy_id, buy_times)
        return FOO.buy_limit_check_by_type(cfg, data, buy_id, g_enum.gift.limit_buy_type.forever, buy_times)
    end
}


--购买检查
FOO.buy_limit_check = function(cfg, userdata, buy_id, buy_times)
    -- 1 刷新次数
    FOO.buy_flush_limit(userdata)

    -- 2 检查
    local buy_type = cfg.limittime
    local func = FOO.BUY_LIMIT_CHECK[buy_type]
    if not func then
        return false
    end
    return func(cfg, userdata, buy_id, buy_times)
end


--购买次数记录
FOO.buy_times_recording = function(cfg, data, buy_id, times)
    local type = cfg.limittime
    data.limit_buy = data.limit_buy or {}
    data.limit_buy[type] = data.limit_buy[type] or {}
    data.limit_buy[type].buy_list = data.limit_buy[type].buy_list or {}
    data.limit_buy[type].buy_list[buy_id] = data.limit_buy[type].buy_list[buy_id] or {}

    --购买次数
    data.limit_buy[type].buy_list[buy_id].times = (data.limit_buy[type].buy_list[buy_id].times or 0) + times

    --购买总次数
    data.limit_buy[type].buy_list[buy_id].all_times = (data.limit_buy[type].buy_list[buy_id].all_times or 0) + times
end


-- 调试日志
FOO.write_log = function(logs, times)
    local get_space = function(level)
        local s = ""
        for i=1, level or 0 do
            s = s .. '---- '
        end
        return s
    end
    if ngx.ctx.log ~= 0 then
        log.loggerdebug("******************************* start *************************************")
        log.loggerdebug("玩家(uin=%%) 第%%次抽奖，抽奖前幸运值：%%，抽奖后幸运值：%%，必得物品：%% ，幸运物品：%%，随机物品：%%",
        ngx.ctx.m_params.uin, times, logs.lucky_value, logs.new_lucky_value, logs.must.items, logs.lucky.items, logs.random.items)

        --抽奖细节
        log.loggerdebug("%% 必得物品池：", get_space(1))
        for _, list in pairs(logs.must.rate_list) do
            log.loggerdebug("%% 必得物品池 %%, 总概率：%%, 物品池概率：%%, 随机概率：%%， 随机到的物品id=%%, 物品数量=%%", get_space(2),
                list.k, list.all_rate, list.pool_rate, list.random_rate,list.itemid or 0, list.itemnum or 0)
        end

        log.loggerdebug("%% 幸运物品池：", get_space(1))
        if next(logs.lucky.items) then
            local info = logs.lucky.rate_list[1]
            local n = 0
            log.loggerdebug("%% 幸运物品的总概率: %%，随机到的概率: %%, 获得的物品： %%", get_space(2),
                info.all_rate, info.random_rate, logs.lucky.items)
            for k, v in ipairs(info.rate_list or {}) do
                local _rate = ((v-n) / info.rate_list[#info.rate_list]) * 100
                log.loggerdebug("%% 随机到幸运物品 %% 的概率范围为 %% ~ %%  占总概率 %% %", get_space(3), k, n+1, v, _rate)
                n = v
            end
        end

        log.loggerdebug("%% 随机物品池：", get_space(1))
        for pool_id, pool_info in ipairs(logs.random.rate_list or {}) do
            log.loggerdebug("%% 随机池 %% , 总概率：%%，池的概率：%%，随机数：%%", get_space(2),
                pool_id, pool_info.all_rate, pool_info.pool_rate, pool_info.random_rate)
            local list = pool_info.list
            if  list then
                log.loggerdebug("%% 随机池 %% 抽中的物品池的总概率：%%，随机数： %%， 物品id:%%, 物品数量:%%", get_space(3),
                    pool_id, list.all_rate, list.random_rate, list.itemid, list.itemnum)
                local n = 0
                for k, v in ipairs(list.rate_list or {}) do
                    local _rate = ((v-n) / list.rate_list[#list.rate_list]) * 100
                    log.loggerdebug("%% 随机池 %% 物品池 %% 的概率范围 %% ~ %%  占总概率 %% %",get_space(4),pool_id, k, n+1, v, _rate)
                    n = v
                end
            else
                log.loggerdebug("%% 未抽中随机物品池 %%", get_space(3), pool_id)
            end
        end
        log.loggerdebug("********************************* bag***********************************")
        uu.var_dump(logs.bag_items)
        log.loggerdebug("******************************  end ****************************************")
    end
end


-- 埋点日志
FOO.write_op_log = function(loginfo)
    if not loginfo then
        return
    end
    for _, logs in ipairs(loginfo.list or {}) do
        local info = {
            action = loginfo.action,
            all_times = logs.times,              --玩家共计抽取礼包次数
            draw_times = loginfo.times,     --本次一共抽取几次
            cost_item_id = loginfo.id,      --玩家消耗的物品id
            cost_item_num = loginfo.num,    --玩家消耗的物品数据
            drop_items = logs.drop_items,        --开启礼包获得的物品
            give_times = loginfo.give_times,        --赠送次数
            old_lucky_value = logs.lucky_value,     --抽之前幸运值
            new_lucky_value = logs.new_lucky_value, --抽纸盒幸运值
            gift_id = loginfo.gift_id,              --礼包id
            is_give = logs.is_give and 1 or 0,
            orderid = loginfo.orderid,
        }
        if loginfo.action == 'welfare_gift_buy' then
            info.buy_id = loginfo.buy_id
        end
        op_log.record("welfare_gift", loginfo.action, info)
    end
end


return FOO